﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Vowei.Core.Models;
using Vowei.Data.Helpers;

namespace Vowei.Data.Models
{
    public class TicketProgress : IContainer<TicketProgress>
    {
        public TicketProgress()
        {
            Children = new List<TicketProgress>();
        }

        IQueryable ITableItemContainer.Children
        {
            get { return Children.AsQueryable(); }
        }

        public List<TicketProgress> Children
        {
            get;
            set;
        }

        public ITableItemContainer ScopedItem { get; set; }

        public int TicketsCount { get; set; }

        public int ActiveTicketsCount { get; set; }

        public int ClosedTicketsCount { get; set; }

        public TimeSpan TotalEstimatedDuration { get; set; }

        public TimeSpan CompletedWorkHours { get; set; }

        public double TotalBusinessValue { get; set; }

        public double EarnedBusinessValue { get; set; }

        class TicketQuery
        {
            public ITableItemContainer ScopedItem { get; set; }

            public IQueryable<Ticket> Query { get; set; }
        }

        public static TicketProgress CreateMilestoneProgressFrom(Milestone milestone, IVoweiContext context)
        {
            var ms = milestone.AllMilestones(context).OrderBy(m => m.StartDate);

            // 将项目本身加入进去
            var msList = ms.ToList();
            msList.Add(milestone);

            var msQuery = from m in msList
                          select new TicketProgress.TicketQuery
                          {
                              ScopedItem = m,
                              Query = m.AllTickets(context)
                          };

            var milestones = msQuery.ToList();

            return TicketProgress.CreateFromImpl<Milestone>(milestone, milestones);
        }

        public static TicketProgress CreateRequirementProgressFrom(Requirement requriement, IVoweiContext context)
        {
            var ms = requriement.AllTickets(context).OfType<Requirement>().OrderBy(m => m.BusinessValue);
            var list = ms.ToList();

            var msQuery = from m in list
                          select new TicketProgress.TicketQuery
                          {
                              ScopedItem = m,
                              Query = m.AllTickets(context)
                          };

            var milestones = msQuery.ToList();

            return TicketProgress.CreateFromImpl<Requirement>(requriement, milestones);
        }

        public static TicketProgress CreateRequirementProgressFrom(Milestone milestone, IVoweiContext context)
        {
            var ms = milestone.AllRequirements(context).OrderBy(m => m.BusinessValue);
            var list = ms.ToList();

            var msQuery = from m in list
                          select new TicketProgress.TicketQuery
                          {
                              ScopedItem = m,
                              Query = m.AllTickets(context)
                          };

            var milestones = msQuery.ToList();

            return TicketProgress.CreateFromImpl<Milestone>(milestone, milestones);
        }

        private static TicketProgress CreateFromImpl<T>(ITableItemContainer root, IList<TicketQuery> collection)
        {
            var progresses = new List<TicketProgress>(collection.Count);
            for (int i = 0; i < collection.Count; ++i)
            {
                var q = collection[i];
                var progress = new TicketProgress()
                {
                    ScopedItem = q.ScopedItem,
                    TicketsCount = q.Query.Count(),
                    ActiveTicketsCount = q.Query.Active().Count(),
                    ClosedTicketsCount = q.Query.Closed().Count(),
                    TotalBusinessValue = q.Query.OfType<Requirement>().Sum(r => r.BusinessValue),
                    EarnedBusinessValue = q.Query.OfType<Requirement>().Closed().Sum(r => r.BusinessValue),
                    TotalEstimatedDuration = TimeSpan.FromTicks(q.Query.OfType<Task>().Sum(r => r.DueDate.Value.Ticks - r.StartDate.Value.Ticks)),
                    CompletedWorkHours = TimeSpan.FromTicks(q.Query.OfType<Task>().Closed().Sum(r => r.DueDate.Value.Ticks - r.StartDate.Value.Ticks)),
                };

                progresses.Add(progress);
            }

            var result = new TicketProgress() { ScopedItem = root };

            for (int i = 0; i < progresses.Count; ++i)
            {
                var item = (ITable)progresses[i].ScopedItem;
                if (root.Children.OfType<ITable>().Any(m => m.ID == item.ID))
                    result.Children.Add(progresses[i]);
            }

            return result;
        }
    }
}
